/*

std::async 是一个用于异步执行函数的模板函数，它返回一个 std::future 对象，该对象用于获取函数的返回值。

*/

#include <iostream>
#include <future>
#include <chrono>
#include <thread>

// 定义一个用来异步的任务
std::string fetchDataFromDB(std::string query)
{
    // 模拟一个异步的人物，假设从从数据库获取数据
    std::this_thread::sleep_for(std::chrono::seconds(5));
    return "Data: " + query;
}

void future_use()
{
    // 使用 std::async 异步调用 上面定义的任务
    std::future<std::string> resultFromDB = std::async(std::launch::async, fetchDataFromDB, "今天是7.26日");

    // 在主线程做其他的事情
    std::cout << "Doing something else..." << std::endl;
    std::this_thread::sleep_for(std::chrono::seconds(3));

    // 从 future 对象中获取数据
    std::string dbData = resultFromDB.get();
    std::cout << dbData << std::endl;
}

void future_wait()
{
    std::future<std::string> resultFromDB = std::async(std::launch::async, fetchDataFromDB, "今天是7.26日");

    std::cout << "main thread 继续执行 task ..." << std::endl;

    // 仅等待 task 完成，不获取结果
    std::cout << "main thread 在wait结果，被阻塞中..." << std::endl;
    std::cout << "异步任务已完成，但尚未获取结果" << std::endl;

    // wait 可以被调用多次，但不获取数据
    resultFromDB.wait();
    std::cout << "main thread 阻塞解封" << std::endl;

    // 获取结果
    std::string result = resultFromDB.get();
    std::cout << "获取结果: " << result << std::endl;
}

void future_get()
{
    std::future<std::string> resultFromDB = std::async(std::launch::async, fetchDataFromDB, "今天是7.26日");

    std::cout << "main thread 继续执行 task ..." << std::endl;

    // 仅等待 task 完成，不获取结果
    std::cout << "main thread 在wait结果，被阻塞中..." << std::endl;
    std::cout << "异步任务已完成，但尚未获取结果" << std::endl;

    // future get 只能获取一次，相当于右值
    std::string result = resultFromDB.get();
    std::cout << "main thread 阻塞解封" << std::endl;

    // 打印结果
    std::cout << "获取结果: " << result << std::endl;
}

int main()
{
    // future_use();

    // future 的 get 与 wait
    future_get();

    std::cout << "1111111111111111" << std::endl;

    return 0;
}

/*

sync的启动策略
std::async函数可以接受几个不同的启动策略，这些策略在std::launch枚举中定义。除了std::launch::async之外，还有以下启动策略：

std::launch::deferred：这种策略意味着任务将在调用std::future::get()或std::future::wait()函数时延迟执行。换句话说，任务将在需要结果时同步执行。
std::launch::async | std::launch::deferred：这种策略是上面两个策略的组合。任务可以在一个单独的线程上异步执行，也可以延迟执行，具体取决于实现。
默认情况下，std::async使用std::launch::async | std::launch::deferred策略。这意味着任务可能异步执行，也可能延迟执行，具体取决于实现。需要注意的是，不同的编译器和操作系统可能会有不同的默认行为

deferred: 更加的轻量级，避免不必要的 thread 创建开销

*/